﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace pyTivoMetadataManager
{
    public partial class MainForm : Form
    {
        private List<FileInfo> mediaFiles;
        private int _mfIndex = 0;

        private Dictionary<string, string> _tvRatings;
        private Dictionary<string, string> _mpaaRatings;
        private Dictionary<string, string> _colorCodes;
        private Dictionary<string, ShowingBits> _showingBits;

        #region Properties
        internal FileInfo CurrentMediaFile
        {
            get { return (mediaFiles[_mfIndex]); }
        }

        internal string MediaName
        {
            get { return (rbMovie.Checked ? txtTitle.Text : txtSeriesTitle.Text); }
        }

        internal string MediaType
        {
            get { return (rbMovie.Checked ? "Movie" : "TV Show"); }
        }

        internal VideoMetadata Metadata
        {
            get { return (_vm); }
            set { _vm = value; }
        }
        #endregion

        public MainForm()
        {
            InitializeComponent();

            _colorCodes = DisplayNameAttribute.GetLookupStructure(typeof(ColorCodes));
            _tvRatings = DisplayNameAttribute.GetLookupStructure(typeof(TvRatings));
            _mpaaRatings = DisplayNameAttribute.GetLookupStructure(typeof(MpaaRatings));
            _showingBits = DisplayNameAttribute.GetLookupStructure<ShowingBits>();

            LoadCollectionControls();

            dtRecordedDate.MaxDate = dtOriginalAirDate.MaxDate = dtReleaseDate.MaxDate = new DateTime(DateTime.Now.Year, 12, 31, 23, 59, 59);            
            LoadMediaDirectory();
        }

        private void LoadCollectionControls()
        {
            foreach (string key in _colorCodes.Keys)
            {
                cboColorCode.Items.Add(key);
            }

            foreach (string key in _tvRatings.Keys)
            {
                cboTvRating.Items.Add(key);
            }

            foreach (string key in _mpaaRatings.Keys)
            {
                cboMpaaRating.Items.Add(key);
            }

            foreach (string key in _showingBits.Keys)
            {
                clbAttributes.Items.Add(key);
            }
        }

        private void btnClose_Click(object sender, EventArgs e)
        {
            CloseForm();
        }

        private void btnPrevious_Click(object sender, EventArgs e)
        {
            if (_isDirty)
            {
                DialogResult dr = MessageBox.Show(this,
                    "You have made changes to this form that are not saved, would you like to save them before changing records?", "Save changes?",
                    MessageBoxButtons.YesNoCancel,
                    MessageBoxIcon.Question,
                    MessageBoxDefaultButton.Button1);
                switch (dr)
                {
                    case DialogResult.Yes:
                        btnSave_Click(sender, e);
                        break;
                    case DialogResult.Cancel:
                        return;
                }
            }
            _mfIndex = (mediaFiles.Count + _mfIndex - 1) % mediaFiles.Count;
            LoadFile(mediaFiles[_mfIndex]);
        }

        private void btnNext_Click(object sender, EventArgs e)
        {
            if (_isDirty)
            {
                DialogResult dr = MessageBox.Show(this, 
                    "You have made changes to this form that are not saved, would you like to save them before changing records?", "Save changes?", 
                    MessageBoxButtons.YesNoCancel, 
                    MessageBoxIcon.Question, 
                    MessageBoxDefaultButton.Button1);
                switch (dr)
                {
                    case DialogResult.Yes:
                        btnSave_Click(sender, e);
                        break;
                    case DialogResult.Cancel:
                        return;
                }
            }
            _mfIndex = (_mfIndex + 1) % mediaFiles.Count;
            LoadFile(mediaFiles[_mfIndex]);
        }

        private void btnLoad_Click(object sender, EventArgs e)
        {
            LoadForm loadForm = new LoadForm(this);
            loadForm.Show(this);
        }

        private void btnSave_Click(object sender, EventArgs e)
        {
            SaveFile();
        }

        private void ClearForm()
        {
            txtTitle.Text = "";
            dtReleaseDate.Value = DateTime.Now;
            dtOriginalAirDate.Value = DateTime.Now;
            dtRecordedDate.Value = DateTime.Now;
            rbMovie.Checked = true;
            txtSeriesTitle.Text = "";
            txtEpisodeTitle.Text = "";
            txtDescription.Text = "";
            txtChannelNbr.Text = "";
            txtChannelName.Text = "";
            clbAttributes.ClearSelected();
            for (int i = 0; i < clbAttributes.Items.Count; i++) clbAttributes.SetItemChecked(i, false);
            try
            {
                cboTvRating.SelectedItem = null;
                cboMpaaRating.SelectedItem = null;
                cboColorCode.SelectedItem = null;
            }
            catch (ArgumentNullException) 
            {
                cboTvRating.SelectedIndex = 0;
                cboMpaaRating.SelectedIndex = 0;
                cboColorCode.SelectedIndex = 0;
            }
            lvPeople.Items.Clear();
            lvGenres.Items.Clear();
            rcStarRating.Value = 0;

            _isDirty = false;
        }

        public void LoadMediaDirectory()
        {
            mediaFiles = new List<FileInfo>();

            DirectoryInfo di = new DirectoryInfo(SettingsSingleton.Instance.MediaPath);
            if (!di.Exists)
            {
                MessageBox.Show("Media directory not found!", "Media Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            FileInfo[] fis = di.GetFiles("*.*", SearchOption.TopDirectoryOnly);
            foreach (FileInfo fi in fis)
            {
                if (!fi.Extension.Equals(".txt"))
                {
                    mediaFiles.Add(fi);
                }
            }
            mediaFiles.Sort(delegate(FileInfo fi1, FileInfo fi2)
            {
                return fi1.Name.CompareTo(fi2.Name);
            });

            _mfIndex = 0;
            LoadFile(mediaFiles[_mfIndex]);

        }

        private VideoMetadata _vm = null;
        private void LoadFile(FileInfo fInfo)
        {
            string metaFile = string.Format("{0}.txt", fInfo.FullName);
            tslFilename.Text = fInfo.Name;

            VideoMetadata vm = new VideoMetadata();
            // Initial defaults
            vm.Title = Path.GetFileNameWithoutExtension(fInfo.Name).Replace("_", " ");
            vm.RecordedTime = fInfo.CreationTime;
            vm.OriginalAirDate = fInfo.CreationTime;
            vm.ColorCode = ColorCodes.ColorSeries;
            vm.ChannelNumber = 0;
            vm.ChannelName = "Internet";
            vm.Attributes = ShowingBits.Stereo;

            if (File.Exists(metaFile))
            {
                vm.LoadFromMetadataFile(metaFile);
            }
            else
            {
                vm.Filename = metaFile;
            }
            LoadMetadata(vm);

            _isDirty = false;
        }

        internal void LoadMetadata(VideoMetadata vm)
        {
            ClearForm();
            _vm = vm;
            txtTitle.Text = _vm.Title;
            txtDescription.Text = _vm.Description;
            rbTVShow.Checked = _vm.IsEpisode;
            txtSeriesTitle.Text = _vm.SeriesTitle;
            txtEpisodeTitle.Text = _vm.EpisodeTitle;
            txtChannelNbr.Text = _vm.ChannelNumber.ToString();
            txtChannelName.Text = _vm.ChannelName;
            if (_vm.OriginalAirDate == null)
            {
                if (_vm.MovieYear != null)
                {
                    dtReleaseDate.Value = new DateTime((int)_vm.MovieYear, 1, 1);
                }
            }
            else
            {
                dtOriginalAirDate.Value = (DateTime)_vm.OriginalAirDate;
                dtReleaseDate.Value = (DateTime)_vm.OriginalAirDate;
            }
            if (_vm.RecordedTime != null) dtRecordedDate.Value = (DateTime)_vm.RecordedTime;
            foreach (Person person in _vm.People)
            {
                lvPeople.Items.Add(person.Name).SubItems.Add(Enum.GetName(typeof(PersonType), person.Type));
            }
            foreach (string genre in _vm.Genres)
            {
                lvGenres.Items.Add(genre);
            }

            foreach (string key in _tvRatings.Keys)
            {
                if (_tvRatings[key].Equals(_vm.TvRating, StringComparison.InvariantCultureIgnoreCase))
                {
                    cboTvRating.SelectedItem = key;
                    break;
                }
            }
            foreach (string key in _mpaaRatings.Keys)
            {
                if (_mpaaRatings[key].Equals(_vm.MpaaRating, StringComparison.InvariantCultureIgnoreCase))
                {
                    cboMpaaRating.SelectedItem = key;
                    break;
                }
            }
            foreach (string key in _colorCodes.Keys)
            {
                if (_colorCodes[key].Equals(_vm.ColorCode, StringComparison.InvariantCultureIgnoreCase))
                {
                    cboColorCode.SelectedItem = key;
                    break;
                }
            }

            int i = 0;
            List<int> selectedBits = new List<int>();
            foreach (string bit in clbAttributes.Items)
            {
                if (_showingBits[bit] == (_vm.Attributes & _showingBits[bit]))
                {
                    selectedBits.Add(i);
                }
                i++;
            }
            foreach (int j in selectedBits)
            {
                clbAttributes.SetItemChecked(j, true);
            }
            if (!string.IsNullOrEmpty(_vm.StarRating)) rcStarRating.Value = (int.Parse(_vm.StarRating.Substring(1)) + 1) / 2;
        }

        private void SaveFile()
        {
            if (_vm != null)
            {
                _vm.IsEpisode = rbTVShow.Checked;
                if (_vm.IsEpisode)
                {
                    _vm.SeriesTitle = txtSeriesTitle.Text;
                    _vm.EpisodeTitle = txtEpisodeTitle.Text;
                    _vm.OriginalAirDate = dtOriginalAirDate.Value;
                }
                else
                {
                    _vm.Title = txtTitle.Text.Trim();
                    _vm.OriginalAirDate = dtReleaseDate.Value;
                    _vm.MovieYear = dtReleaseDate.Value.Year;
                }
                _vm.Description = txtDescription.Text;
                int channelNbr;
                if (int.TryParse(txtChannelNbr.Text, out channelNbr)) _vm.ChannelNumber = channelNbr;
                _vm.ChannelName = txtChannelName.Text;
                _vm.RecordedTime = dtRecordedDate.Value;
                if (cboTvRating.SelectedItem != null) _vm.TvRating = _tvRatings[cboTvRating.SelectedItem.ToString()];
                if (cboMpaaRating.SelectedItem != null) _vm.MpaaRating = _mpaaRatings[cboMpaaRating.SelectedItem.ToString()];
                if (cboColorCode.SelectedItem != null) _vm.ColorCode = _colorCodes[cboColorCode.SelectedItem.ToString()];
                _vm.People.Clear();
                foreach (ListViewItem lvi in lvPeople.Items)
                {
                    _vm.People.Add(
                        new Person
                        {
                            Name = lvi.Text,
                            Type = (PersonType)Enum.Parse(typeof(PersonType), lvi.SubItems[1].Text)
                        });
                }
                _vm.Genres.Clear();
                foreach (ListViewItem lvi in lvGenres.Items)
                {
                    _vm.Genres.Add(lvi.Text);
                }

                ShowingBits showingBits = (ShowingBits)0;
                foreach (string showingBit in clbAttributes.CheckedItems)
                {
                    showingBits |= (ShowingBits)Enum.Parse(typeof(ShowingBits), showingBit);
                }
                _vm.Attributes = showingBits;
                if (rcStarRating.Value > 0)
                {
                    _vm.StarRating = "x" + ((rcStarRating.Value * 2) - 1);
                }

                _vm.SaveToMetadataFile(_vm.Filename);
                _isDirty = false;
            }
        }

        private void CloseForm()
        {
            if (_isDirty)
            {
                DialogResult dr = MessageBox.Show(this,
                    "You have made changes to this form that are not saved, would you like to save them before closing?", "Save changes?",
                    MessageBoxButtons.YesNoCancel,
                    MessageBoxIcon.Question,
                    MessageBoxDefaultButton.Button1);
                switch (dr)
                {
                    case DialogResult.Yes:
                        SaveFile();
                        break;
                    case DialogResult.Cancel:
                        return;
                }
            }
            this.Close();
        }

        private void btnAddPerson_Click(object sender, EventArgs e)
        {
            AddPersonForm window = new AddPersonForm(this);
            window.Show(this);
        }

        public void AddPerson(string name, string type)
        {
            lvPeople.Items.Add(name).SubItems.Add(type);
            MarkDirty(this, new EventArgs());
        }

        public void AddGenre(string genre)
        {
            lvGenres.Items.Add(genre);
            MarkDirty(this, new EventArgs());
        }

        private void rbMovie_CheckedChanged(object sender, EventArgs e)
        {
            if (rbMovie.Checked)
            {
                gbTVShow.Enabled = rbTVShow.Checked = false;
                rbTVShow.Enabled = gbMovie.Enabled = true;
                
            }
            MarkDirty(sender, e);
        }

        private void rbTVShow_CheckedChanged(object sender, EventArgs e)
        {
            if (rbTVShow.Checked)
            {
                gbMovie.Enabled = rbMovie.Checked = false;
                rbMovie.Enabled = gbTVShow.Enabled = true;
            }
            MarkDirty(sender, e);
        }

        private void btnRemovePerson_Click(object sender, EventArgs e)
        {
            foreach (ListViewItem lvi in lvPeople.SelectedItems)
            {
                lvPeople.Items.Remove(lvi);
            }
            MarkDirty(sender, e);
        }

        private void lvPeople_SelectedIndexChanged(object sender, EventArgs e)
        {
            btnRemovePerson.Enabled = true;
        }

        private void lvGenres_SelectedIndexChanged(object sender, EventArgs e)
        {
            btnRemoveGenre.Enabled = true;
        }

        private void btnRemoveGenre_Click(object sender, EventArgs e)
        {
            foreach (ListViewItem lvi in lvGenres.SelectedItems)
            {
                lvGenres.Items.Remove(lvi);
            }
            MarkDirty(sender, e);
        }

        private void btnAddGenre_Click(object sender, EventArgs e)
        {
            AddGenreForm window = new AddGenreForm(this);
            window.Show(this);
        }

        private bool _isDirty = false;
        private void MarkDirty(object sender, EventArgs e)
        {
            _isDirty = true;
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            CloseForm();
        }

        private void saveToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SaveFile();
        }

        private void settingsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SettingsForm settingsForm = new SettingsForm(this);
            settingsForm.Show(this);
        }

        private void txtSeriesTitle_Leave(object sender, EventArgs e)
        {
            /*
            if (string.IsNullOrEmpty(txtSeriesId.Text.Trim()))
            {
                string seriesId = SeriesId.GetSeriesId(txtSeriesTitle.Text.Trim());
                if (!string.IsNullOrEmpty(seriesId))
                {
                    txtSeriesId.Text = seriesId;
                }
            }
            */
        }
    }
}
